<?php
/**
 * Created By PhpStorm
 * Author: patrick wu
 * Date: 2020/9/22
 * Time: 9:26
 */
namespace App\Utils;

use Carbon\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Arr;
use OSS\OssClient;
use OSS\Core\OssException;

/**
 * 文件上传到阿里对象服务器辅助类
 * Class UploadAliOss
 * @package App\Utils
 */
class UploadAliOss
{
    protected $access_id;           //阿里账号 access_id

    protected $access_secret;       //阿里账号 access_secret

    protected $end_point;           //阿里服务器地址

    protected $allow_bucket;        //允许创建的存储空间名

    public $oos_client;             //上传的实例类

    protected $path_prefix;         //文件前缀

    public function __construct()
    {
        $ali_config =   Config::get('upload.ali_oss');

        $this->access_id    =   $ali_config['access_key_id'] ?? '';
        $this->access_secret=   $ali_config['access_key_secret'] ?? '';
        $this->end_point    =   $ali_config['end_point'] ?? '';
        $this->allow_bucket =   $ali_config['allow_bucket'] ?? [];

        $this->oos_client   =   new OssClient($this->access_id, $this->access_secret, $this->end_point);
        $this->path_prefix  =   ($ali_config['path_prefix'] ?? '') . '/' . Carbon::now()->toDateString() . '/';
    }

    /**
     * 创建存储空间
     * @param string $bucket_name   存储空间名
     * @return array
     */
    private function createBucket(string $bucket_name)
    {
        if (!empty($this->allow_bucket) && in_array($bucket_name, $this->allow_bucket)) {
            return [false, '存储空间不允许创建'];
        }

        try {
            // 设置存储空间的存储类型为低频访问类型，默认是标准类型。
            $options    =   [
                OssClient::OSS_STORAGE => OssClient::OSS_STORAGE_IA
            ];

            // 设置存储空间的权限为公共读，默认是私有读写。
            $result  =   $this->oos_client->createBucket($bucket_name, OssClient::OSS_ACL_TYPE_PUBLIC_READ, $options);
            return [true, $result];
        } catch (OssException $e) {
            return [false, $e->getMessage()];
        }
    }

    /**
     * 检测存储空间是否存在
     * @param string $bucket_name   存储空间名
     * @return bool
     */
    public function existsBucket(string $bucket_name)
    {
        try {
            return $this->oos_client->doesBucketExist($bucket_name);
        } catch (OssException $e) {
            return false;
        }
    }

    /**
     * 多文件上传
     * @param array $file_object    上传文件列表 (key 为 文件名，value 为 文件地址)
     * @param string $bucket_name   存储空间名
     * @return array
     */
    public function uploadFile(array $file_object, string $bucket_name = 'wanghongcheng')
    {
        if (empty($file_object)) {
            return [false, '上传文件不能为空'];
        }

        if (!$this->existsBucket($bucket_name)) {
            [$flag, $result]    =   $this->createBucket($bucket_name);
            if (!$flag) {
                return [false, $result];
            }
        }

        $file_object    =   array_slice($file_object, 0, 100);
        $success_file   =   [];
        foreach ($file_object as $file_name => $file_path) {
            try{
                $file_name  =   is_numeric($file_name) ? md5_file($file_path) : $file_name;
                $upload     =   $this->oos_client->uploadFile($bucket_name, $this->path_prefix . $file_name, $file_path);
                $success_file[$file_name]   =   $upload['oss-request-url'] ?? '';
            } catch(OssException $e) {
                $this->deleteFile($bucket_name, array_keys($success_file));
                return [false, $e->getMessage()];
            }
        }

        return [true, $success_file];
    }

    /**
     * 多文件删除
     * @param string $bucket_name   存储空间名
     * @param array $file_object    删除文件列表
     * @return bool
     */
    public function deleteFile(string $bucket_name, array $file_object)
    {
        try{
            $this->oos_client->deleteObjects($bucket_name, $file_object);
            return true;
        } catch(OssException $e) {
            return false;
        }
    }

}
